"""
报告生成器基础模块

提供报告生成的基础框架和通用功能。
"""

from typing import Dict, List, Optional, Any, Union
from datetime import datetime, timedelta
from dataclasses import dataclass, field
from enum import Enum
from abc import ABC, abstractmethod
import json
import csv
import io
from pathlib import Path


class ReportType(Enum):
    """报告类型"""
    TRADING = "trading"  # 交易报告
    PERFORMANCE = "performance"  # 绩效报告
    RISK = "risk"  # 风险报告
    POSITION = "position"  # 持仓报告
    PORTFOLIO = "portfolio"  # 组合报告
    DAILY = "daily"  # 日报
    WEEKLY = "weekly"  # 周报
    MONTHLY = "monthly"  # 月报
    QUARTERLY = "quarterly"  # 季报
    ANNUAL = "annual"  # 年报


class ReportFormat(Enum):
    """报告格式"""
    JSON = "json"
    CSV = "csv"
    HTML = "html"
    PDF = "pdf"
    EXCEL = "excel"
    TEXT = "text"


@dataclass
class ReportConfig:
    """报告配置"""
    report_type: ReportType
    format: ReportFormat
    title: str
    description: Optional[str] = None
    
    # 时间范围
    start_date: Optional[datetime] = None
    end_date: Optional[datetime] = None
    
    # 输出配置
    output_path: Optional[str] = None
    filename: Optional[str] = None
    
    # 样式配置
    template: Optional[str] = None
    style: Dict[str, Any] = field(default_factory=dict)
    
    # 数据配置
    include_charts: bool = True
    include_tables: bool = True
    include_summary: bool = True
    include_details: bool = True
    
    # 其他配置
    language: str = "zh-CN"
    timezone: str = "Asia/Shanghai"
    decimal_places: int = 4
    
    created_time: datetime = field(default_factory=datetime.now)


@dataclass
class ReportData:
    """报告数据"""
    title: str
    subtitle: Optional[str] = None
    summary: Dict[str, Any] = field(default_factory=dict)
    sections: List[Dict[str, Any]] = field(default_factory=list)
    charts: List[Dict[str, Any]] = field(default_factory=list)
    tables: List[Dict[str, Any]] = field(default_factory=list)
    metadata: Dict[str, Any] = field(default_factory=dict)
    
    generated_time: datetime = field(default_factory=datetime.now)


class ReportGenerator(ABC):
    """
    报告生成器基类
    
    定义报告生成的通用接口和基础功能。
    """
    
    def __init__(self, config: ReportConfig):
        """初始化报告生成器"""
        self.config = config
        self.data: Optional[ReportData] = None
    
    @abstractmethod
    def collect_data(self, **kwargs) -> ReportData:
        """收集报告数据"""
        pass
    
    @abstractmethod
    def generate_content(self, data: ReportData) -> str:
        """生成报告内容"""
        pass
    
    def format_number(self, value: Union[int, float], format_type: str = "default") -> str:
        """格式化数字"""
        if value is None:
            return "N/A"
        
        decimal_places = self.config.decimal_places
        
        if format_type == "percentage":
            return f"{value:.{decimal_places}%}"
        elif format_type == "currency":
            return f"¥{value:,.{decimal_places}f}"
        elif format_type == "integer":
            return f"{int(value):,}"
        else:
            return f"{value:,.{decimal_places}f}"
    
    def format_datetime(self, dt: datetime, format_type: str = "default") -> str:
        """格式化日期时间"""
        if dt is None:
            return "N/A"
        
        if format_type == "date":
            return dt.strftime("%Y-%m-%d")
        elif format_type == "time":
            return dt.strftime("%H:%M:%S")
        elif format_type == "datetime":
            return dt.strftime("%Y-%m-%d %H:%M:%S")
        else:
            return dt.strftime("%Y-%m-%d %H:%M:%S")
    
    def create_table(
        self,
        title: str,
        headers: List[str],
        rows: List[List[Any]],
        format_rules: Optional[Dict[str, str]] = None
    ) -> Dict[str, Any]:
        """创建表格"""
        formatted_rows = []
        
        for row in rows:
            formatted_row = []
            for i, cell in enumerate(row):
                if format_rules and i < len(headers):
                    header = headers[i]
                    if header in format_rules:
                        if isinstance(cell, (int, float)):
                            formatted_cell = self.format_number(cell, format_rules[header])
                        elif isinstance(cell, datetime):
                            formatted_cell = self.format_datetime(cell, format_rules[header])
                        else:
                            formatted_cell = str(cell)
                    else:
                        formatted_cell = str(cell)
                else:
                    formatted_cell = str(cell)
                formatted_row.append(formatted_cell)
            formatted_rows.append(formatted_row)
        
        return {
            "type": "table",
            "title": title,
            "headers": headers,
            "rows": formatted_rows,
            "row_count": len(formatted_rows),
            "column_count": len(headers)
        }
    
    def create_chart(
        self,
        title: str,
        chart_type: str,
        data: Dict[str, Any],
        options: Optional[Dict[str, Any]] = None
    ) -> Dict[str, Any]:
        """创建图表"""
        return {
            "type": "chart",
            "chart_type": chart_type,
            "title": title,
            "data": data,
            "options": options or {}
        }
    
    def create_section(
        self,
        title: str,
        content: Union[str, Dict[str, Any], List[Any]],
        section_type: str = "text"
    ) -> Dict[str, Any]:
        """创建报告章节"""
        return {
            "type": section_type,
            "title": title,
            "content": content
        }
    
    def generate_to_json(self, data: ReportData) -> str:
        """生成JSON格式报告"""
        report_dict = {
            "title": data.title,
            "subtitle": data.subtitle,
            "generated_time": data.generated_time.isoformat(),
            "summary": data.summary,
            "sections": data.sections,
            "charts": data.charts,
            "tables": data.tables,
            "metadata": data.metadata
        }
        
        return json.dumps(report_dict, ensure_ascii=False, indent=2)
    
    def generate_to_csv(self, data: ReportData) -> str:
        """生成CSV格式报告"""
        output = io.StringIO()
        writer = csv.writer(output)
        
        # 写入标题
        writer.writerow([data.title])
        if data.subtitle:
            writer.writerow([data.subtitle])
        writer.writerow([f"生成时间: {self.format_datetime(data.generated_time)}"])
        writer.writerow([])
        
        # 写入摘要
        if data.summary:
            writer.writerow(["摘要"])
            for key, value in data.summary.items():
                writer.writerow([key, str(value)])
            writer.writerow([])
        
        # 写入表格数据
        for table in data.tables:
            writer.writerow([table["title"]])
            writer.writerow(table["headers"])
            for row in table["rows"]:
                writer.writerow(row)
            writer.writerow([])
        
        return output.getvalue()
    
    def generate_to_html(self, data: ReportData) -> str:
        """生成HTML格式报告"""
        html_parts = []
        
        # HTML头部
        html_parts.append("""
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{title}</title>
    <style>
        body {{ font-family: 'Microsoft YaHei', Arial, sans-serif; margin: 20px; }}
        .header {{ text-align: center; margin-bottom: 30px; }}
        .title {{ font-size: 24px; font-weight: bold; color: #333; }}
        .subtitle {{ font-size: 16px; color: #666; margin-top: 10px; }}
        .generated-time {{ font-size: 12px; color: #999; margin-top: 10px; }}
        .section {{ margin: 20px 0; }}
        .section-title {{ font-size: 18px; font-weight: bold; color: #333; margin-bottom: 10px; }}
        .summary {{ background: #f5f5f5; padding: 15px; border-radius: 5px; }}
        .summary-item {{ margin: 5px 0; }}
        table {{ width: 100%; border-collapse: collapse; margin: 10px 0; }}
        th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
        th {{ background-color: #f2f2f2; font-weight: bold; }}
        .number {{ text-align: right; }}
    </style>
</head>
<body>
""".format(title=data.title))
        
        # 标题部分
        html_parts.append(f"""
    <div class="header">
        <div class="title">{data.title}</div>
        {f'<div class="subtitle">{data.subtitle}</div>' if data.subtitle else ''}
        <div class="generated-time">生成时间: {self.format_datetime(data.generated_time)}</div>
    </div>
""")
        
        # 摘要部分
        if data.summary:
            html_parts.append('<div class="section"><div class="section-title">摘要</div><div class="summary">')
            for key, value in data.summary.items():
                html_parts.append(f'<div class="summary-item"><strong>{key}:</strong> {value}</div>')
            html_parts.append('</div></div>')
        
        # 章节内容
        for section in data.sections:
            html_parts.append(f'<div class="section"><div class="section-title">{section["title"]}</div>')
            if isinstance(section["content"], str):
                html_parts.append(f'<div>{section["content"]}</div>')
            elif isinstance(section["content"], dict):
                html_parts.append(f'<pre>{json.dumps(section["content"], ensure_ascii=False, indent=2)}</pre>')
            html_parts.append('</div>')
        
        # 表格
        for table in data.tables:
            html_parts.append(f'<div class="section"><div class="section-title">{table["title"]}</div>')
            html_parts.append('<table>')
            
            # 表头
            html_parts.append('<tr>')
            for header in table["headers"]:
                html_parts.append(f'<th>{header}</th>')
            html_parts.append('</tr>')
            
            # 表格数据
            for row in table["rows"]:
                html_parts.append('<tr>')
                for cell in row:
                    # 判断是否为数字
                    css_class = "number" if str(cell).replace('.', '').replace('-', '').replace(',', '').isdigit() else ""
                    html_parts.append(f'<td class="{css_class}">{cell}</td>')
                html_parts.append('</tr>')
            
            html_parts.append('</table></div>')
        
        # HTML尾部
        html_parts.append("""
</body>
</html>
""")
        
        return ''.join(html_parts)
    
    def generate_to_text(self, data: ReportData) -> str:
        """生成文本格式报告"""
        lines = []
        
        # 标题
        lines.append("=" * 60)
        lines.append(data.title.center(60))
        if data.subtitle:
            lines.append(data.subtitle.center(60))
        lines.append(f"生成时间: {self.format_datetime(data.generated_time)}".center(60))
        lines.append("=" * 60)
        lines.append("")
        
        # 摘要
        if data.summary:
            lines.append("摘要")
            lines.append("-" * 20)
            for key, value in data.summary.items():
                lines.append(f"{key}: {value}")
            lines.append("")
        
        # 章节
        for section in data.sections:
            lines.append(section["title"])
            lines.append("-" * len(section["title"]))
            if isinstance(section["content"], str):
                lines.append(section["content"])
            else:
                lines.append(str(section["content"]))
            lines.append("")
        
        # 表格
        for table in data.tables:
            lines.append(table["title"])
            lines.append("-" * len(table["title"]))
            
            # 计算列宽
            col_widths = []
            for i, header in enumerate(table["headers"]):
                max_width = len(header)
                for row in table["rows"]:
                    if i < len(row):
                        max_width = max(max_width, len(str(row[i])))
                col_widths.append(max_width + 2)
            
            # 表头
            header_line = "|".join(header.ljust(col_widths[i]) for i, header in enumerate(table["headers"]))
            lines.append(header_line)
            lines.append("-" * len(header_line))
            
            # 数据行
            for row in table["rows"]:
                row_line = "|".join(str(row[i]).ljust(col_widths[i]) if i < len(row) else "".ljust(col_widths[i]) 
                                  for i in range(len(table["headers"])))
                lines.append(row_line)
            lines.append("")
        
        return "\n".join(lines)
    
    def save_report(self, content: str, filename: Optional[str] = None) -> str:
        """保存报告到文件"""
        if filename is None:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"{self.config.report_type.value}_report_{timestamp}.{self.config.format.value}"
        
        if self.config.output_path:
            output_path = Path(self.config.output_path)
            output_path.mkdir(parents=True, exist_ok=True)
            filepath = output_path / filename
        else:
            filepath = Path(filename)
        
        with open(filepath, 'w', encoding='utf-8') as f:
            f.write(content)
        
        return str(filepath)
    
    def generate_report(self, **kwargs) -> str:
        """生成完整报告"""
        # 收集数据
        self.data = self.collect_data(**kwargs)
        
        # 根据格式生成内容
        if self.config.format == ReportFormat.JSON:
            content = self.generate_to_json(self.data)
        elif self.config.format == ReportFormat.CSV:
            content = self.generate_to_csv(self.data)
        elif self.config.format == ReportFormat.HTML:
            content = self.generate_to_html(self.data)
        elif self.config.format == ReportFormat.TEXT:
            content = self.generate_to_text(self.data)
        else:
            content = self.generate_content(self.data)
        
        # 保存文件
        if self.config.output_path or self.config.filename:
            filepath = self.save_report(content, self.config.filename)
            return f"报告已生成: {filepath}"
        
        return content